package com.sangeng.config;

import com.sangeng.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;
    @Autowired
    private AccessDeniedHandler accessDeniedHandler;

    @Bean
    public PasswordEncoder passwordEncoder(){
        // 使用BCryptPasswordEncoder加密
        // return new BCryptPasswordEncoder();
        // 自定义用户加密
        return new MD5PasswordEncoder();
    }
    /**
     * 自定义用户Service验证
     * @return
     */
//    @Bean
//    public PasswordEncoder customUserService() {
//        return new MD5PasswordEncoder();
//    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            //关闭csrf
            .csrf().disable()
            //不通过Session获取SecurityContext
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            // 对于登录接口 允许匿名访问
            .antMatchers("/user/login").permitAll()
            // 除上面外的所有请求全部需要鉴权认证
            .anyRequest().authenticated();
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);


        /*
        我们还希望在认证失败或者是授权失败的情况下也能和我们的接口一样返回相同结构的json，这样可以
        让前端能对响应进行统一的处理。要实现这个功能我们需要知道SpringSecurity的异常处理机制。
        在SpringSecurity中，如果我们在认证或者授权的过程中出现了异常会被ExceptionTranslationFilter捕
        获到。在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。
        如果是认证过程中出现的异常会被封装成AuthenticationException然后调用
        AuthenticationEntryPoint对象的方法去进行异常处理。
        如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对
        象的方法去进行异常处理。
        所以如果我们需要自定义异常处理，我们只需要自定义AuthenticationEntryPoint和
        AccessDeniedHandler然后配置给SpringSecurity即可。
        * */
        //配置异常处理器
        // http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).accessDeniedHandler(accessDeniedHandler);
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
